#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "appconst.h"
#include <QResizeEvent>
#include <QTimerEvent>
#include "dialogfrequence.h"
#include "dialogprogram.h"
#include "dialogloop.h"
#include "dialogconfig.h"
#include "dialoguser.h"
#include "Path.h"
#include "userdatarole.h"
#include "appsettings.h"

#include <QDrag>
#include <QMimeData>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_layoutMode(PlayerLayout::kNine),
    m_lastMode(m_layoutMode),
    m_currentIndex(),
    m_isLooping(),
    m_timerLoop(),
    m_loopIndex()
{
    ui->setupUi(this);

    ui->menuBar->setContextMenuPolicy(Qt::PreventContextMenu);
    ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);

    bool visible = AppSettings::getBool("App/Toolbar", false);
    ui->mainToolBar->setVisible(visible);



    setupPlayerWidget();
    setupSignal();

    updateWindowTitle();

    setupProgram();
    refreshProgramTree();
	
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setupPlayerWidget()
{
    int idx = 0;
    m_playerWidgets[idx ++] = ui->widgetPlayer1;
    m_playerWidgets[idx ++] = ui->widgetPlayer2;
    m_playerWidgets[idx ++] = ui->widgetPlayer3;
    m_playerWidgets[idx ++] = ui->widgetPlayer4;
    m_playerWidgets[idx ++] = ui->widgetPlayer5;
    m_playerWidgets[idx ++] = ui->widgetPlayer6;
    m_playerWidgets[idx ++] = ui->widgetPlayer7;
    m_playerWidgets[idx ++] = ui->widgetPlayer8;
    m_playerWidgets[idx ++] = ui->widgetPlayer9;
    m_playerWidgets[idx ++] = ui->widgetPlayer10;
    m_playerWidgets[idx ++] = ui->widgetPlayer11;
    m_playerWidgets[idx ++] = ui->widgetPlayer12;
    m_playerWidgets[idx ++] = ui->widgetPlayer13;
    m_playerWidgets[idx ++] = ui->widgetPlayer14;
    m_playerWidgets[idx ++] = ui->widgetPlayer15;
    m_playerWidgets[idx ++] = ui->widgetPlayer16;

    m_layoutMode = PlayerLayout::kNine;
    setCurrentIndex(0);
}

void MainWindow::setupSignal()
{
    for (int i = 0; i < AppConst::MAX_PLAYER; i ++)
    {
        m_playerWidgets[i]->setIndex(i);
        connect(m_playerWidgets[i], &PlayerWidget::clicked, this, &MainWindow::onPlayerClicked);
        connect(m_playerWidgets[i], &PlayerWidget::rclicked, this, &MainWindow::onPlayerRClicked);
        connect(m_playerWidgets[i], &PlayerWidget::dbclicked, this, &MainWindow::onPlayerDbclicked);

        connect(m_playerWidgets[i], &PlayerWidget::mediaEnd, this, &MainWindow::onPlayerMediaEnd);

        connect(m_playerWidgets[i], &PlayerWidget::dragDropped, this, &MainWindow::onPlayerDragDropped);

    }

}

void MainWindow::layoutPlayer(PlayerLayout::Mode mode)
{
    QRect rc = ui->framePlayer->rect();
    PlayerLayout::QRectArray rects = m_layout.calcLayout(rc, mode);

    int start = 0;
    if (mode == PlayerLayout::kOne)
    {
        start = m_currentIndex;
    }

    for (size_t i = 0; i < rects.size(); i++)
    {
        int idx = (start + i) % AppConst::MAX_PLAYER;
        m_playerWidgets[idx]->setGeometry(rects[i]);
        m_playerWidgets[idx]->setVisible(true);
    }

    for (size_t i = 0; i < (AppConst::MAX_PLAYER - rects.size()); i ++)
    {
        int idx = (start + i + rects.size()) % AppConst::MAX_PLAYER;
        m_playerWidgets[idx]->setVisible(false);
    }

}


int MainWindow::getCurrentIndex()
{
    return m_currentIndex;
}

void MainWindow::setCurrentIndex(int idx)
{
    if (idx >= 0 && idx < AppConst::MAX_PLAYER)
    {
        m_playerWidgets[m_currentIndex]->setChecked(false);

        m_currentIndex = idx;

        m_playerWidgets[m_currentIndex]->setChecked(true);
    }
}

void MainWindow::setLayoutMode(PlayerLayout::Mode mode)
{
    m_lastMode = m_layoutMode;

    m_layoutMode = mode;
    layoutPlayer(m_layoutMode);
}


void MainWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);

    layoutPlayer(m_layoutMode);
}

void MainWindow::showEvent(QShowEvent *event)
{
    QMainWindow::showEvent(event);

    layoutPlayer(m_layoutMode);

}

void MainWindow::timerEvent(QTimerEvent * event)
{
    int timerId = event->timerId();
    if (timerId == m_timerLoop)
    {
        loopPlay();
    }
}

void MainWindow::closeEvent(QCloseEvent * event)
{
    stopAll();
    stopLoop();

    QMainWindow::closeEvent(event);
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    int key = event->key();
    if (key == Qt::Key_Escape)
    {
        showFull(false);
    }

    QMainWindow::keyPressEvent(event);
}


void MainWindow::stopAll()
{
    for (int i = 0; i < AppConst::MAX_PLAYER; i ++)
    {
        m_playerWidgets[i]->close();
    }
}

void MainWindow::stop(int index)
{
    if (index >= 0 && index < AppConst::MAX_PLAYER)
    {
        m_playerWidgets[index]->close();
    }
}

void MainWindow::start(int index, const QString& url)
{
    if (index < 0 || index >= AppConst::MAX_PLAYER)
    {
        return;
    }

    m_playerWidgets[index]->close();

    m_playerWidgets[index]->open(url);

}

void MainWindow::showFull(bool fullscreen)
{
    if (fullscreen)
    {
        ui->menuBar->hide();
        ui->mainToolBar->hide();
        ui->treeWidget->hide();

        QMargins margins(0,0,0,0);
        ui->centralWidget->layout()->setContentsMargins(margins);

        showFullScreen();
    }
    else
    {
        ui->menuBar->show();
        ui->mainToolBar->show();
        ui->treeWidget->show();

        QMargins margins(4,4,4,4);
        ui->centralWidget->layout()->setContentsMargins(margins);

        showNormal();
    }

}



void MainWindow::onPlayerClicked(int index)
{
    setCurrentIndex(index);
}

void MainWindow::onPlayerRClicked(int index)
{
    QMenu menu;
//    QFont font = menu.font();
//    font.setPointSize(font.pointSize() * 3/2);
//    menu.setFont(font);

    menu.addAction(QIcon(":/images/stop"), tr("Stop"), this, SLOT(on_pushButtonStop_clicked()));
    menu.addAction(QIcon(":/images/stopall"), tr("StopAll"), this, SLOT(on_pushButtonStopAll_clicked()));
    menu.addSeparator();

    menu.addAction(QIcon(":/images/one"), tr("One"), this, SLOT(on_actionOne_triggered()));
    menu.addAction(QIcon(":/images/four"), tr("Four"), this, SLOT(on_actionFour_triggered()));
    menu.addAction(QIcon(":/images/nine"), tr("Nine"), this, SLOT(on_actionNine_triggered()));
    menu.addAction(QIcon(":/images/sixteen"), tr("Sixteen"), this, SLOT(on_actionSixteen_triggered()));

    menu.addSeparator();

    menu.exec(QCursor::pos());
}

void MainWindow::onPlayerDbclicked(int index)
{
    setCurrentIndex(index);

    if (m_layoutMode == PlayerLayout::kOne)
    {
        setLayoutMode(m_lastMode);
    }
    else
    {
        setLayoutMode(PlayerLayout::kOne);
    }
}

void MainWindow::onPlayerMediaEnd(int index)
{

}

void MainWindow::onPlayerDragDropped(int index, const QString& url, const QString& id, const QString& name)
{
    start(index, url);
}

void MainWindow::on_actionFullscreen_triggered()
{
    bool isFull = isFullScreen();
    showFull(!isFull);
}

void MainWindow::on_actionLoop_triggered()
{
    if (isLooping())
    {
        stopLoop();

        stopAll();
    }
    else
    {
        startLoop();
    }
}

void MainWindow::on_actionfreq_triggered()
{
    DialogFrequence dlg;
    dlg.setFreqList(m_freqList);

    dlg.exec();

    m_freqList = dlg.getFreqList();
    m_freqList.save(AppConst::getFreqPath().c_str());

    refreshProgramTree();
}

void MainWindow::on_actionprogram_triggered()
{
    DialogProgram dlg;
    dlg.setFreqList(m_freqList);
    dlg.setProgramList(m_programList);

    dlg.exec();

    m_programList = dlg.getProgramList();
    m_programList.save(AppConst::getProgramPath().c_str());

    refreshProgramTree();
}

void MainWindow::on_actionconfig_triggered()
{
    DialogConfig dlg;

    dlg.setUser(getUser());

    connect(&dlg, &DialogConfig::clickClearFreq, this, &MainWindow::on_clickClearFreq);
    connect(&dlg, &DialogConfig::clickClearProgram, this, &MainWindow::on_clickClearProgram);
    connect(&dlg, &DialogConfig::clickClearLoop, this, &MainWindow::on_clickClearLoop);

    dlg.exec();

    updateWindowTitle();
}

void MainWindow::on_actionusers_triggered()
{
    DialogUser dlg;
    dlg.setUser(getUser());
	dlg.setDataStore(getApp().getSecureDataStore());

    dlg.exec();
}

void MainWindow::on_actionmanage_triggered()
{
    DialogLoop dlg;
    dlg.setProgramList(m_freqList, m_programList);
    dlg.setLoopList(m_loopList);

    dlg.exec();

    m_loopList = dlg.getLoopList();
    m_loopList.save(AppConst::getLoopPath().c_str());
}

void MainWindow::on_actionexit_triggered()
{
    close();
}

void MainWindow::on_pushButtonStop_clicked()
{
    stop(m_currentIndex);
}

void MainWindow::on_pushButtonStopAll_clicked()
{
    stopAll();

    stopLoop();
}

void MainWindow::on_actionOne_triggered()
{
    setLayoutMode(PlayerLayout::kOne);
}

void MainWindow::on_actionFour_triggered()
{
    setLayoutMode(PlayerLayout::kFour);
}

void MainWindow::on_actionNine_triggered()
{
    setLayoutMode(PlayerLayout::kNine);
}

void MainWindow::on_actionSixteen_triggered()
{
    setLayoutMode(PlayerLayout::kSixteen);
}

void MainWindow::startLoop()
{
    if (m_isLooping)
    {
        return;
    }

    if (m_loopList.empty())
    {
        return;
    }

    m_isLooping = true;

    setCurrentIndex(0);

    int layout = AppSettings::getInt("Loop/Layout", AppConst::LOOP_LAYOUT);
    setLayoutMode((PlayerLayout::Mode)(layout));

    int duration = AppSettings::getInt("Loop/Duration", AppConst::LOOP_DURATION);
    m_timerLoop = startTimer(duration * 1000);

    loopPlay();
}

void MainWindow::stopLoop()
{
    if (m_timerLoop > 0)
    {
        killTimer(m_timerLoop);
        m_timerLoop = 0;
    }

    m_isLooping = false;

    m_loopIndex = 0;
}

bool MainWindow::isLooping()
{
    return m_isLooping;
}

PlayerApplication& MainWindow::getApp()
{
	PlayerApplication* app = (PlayerApplication*)QCoreApplication::instance();
	return *app;
}


void MainWindow::setupProgram()
{
    m_freqList.load(AppConst::getFreqPath().c_str());
    m_programList.load(AppConst::getProgramPath().c_str());

    m_loopList.load(AppConst::getLoopPath().c_str());

}

void MainWindow::refreshProgramTree()
{
    ui->treeWidget->clear();

    for (size_t i = 0; i < m_freqList.size(); ++ i)
    {
        const tv::Frequence& freq = m_freqList[i];
        QTreeWidgetItem* item = new QTreeWidgetItem();

        item->setData(0, kNumRole, freq.num.c_str());

        item->setText(0, freq.name.c_str());
        item->setIcon(0, QIcon(":/images/freq"));

        ui->treeWidget->insertTopLevelItem(i, item);
    }

    for (size_t i = 0; i < m_programList.size(); ++ i)
    {
        const tv::Program& program = m_programList[i];
        QTreeWidgetItem* topItem = findFreqItem(program.freqNum);
        if (!topItem)
        {
            continue;
        }

        QTreeWidgetItem* item = new QTreeWidgetItem();

        item->setData(0, kNumRole, program.num.c_str());
        item->setData(0, kNameRole, program.name.c_str());
        item->setData(0, kUrlRole, program.url.c_str());

        item->setText(0, program.name.c_str());
        item->setIcon(0, QIcon(":/images/program"));

        topItem->addChild(item);
    }


    ui->treeWidget->expandAll();
}

QTreeWidgetItem* MainWindow::findFreqItem(const std::string& num)
{
    QTreeWidgetItem* item = NULL;
    int count = ui->treeWidget->topLevelItemCount();
    for (int i = 0; i < count; i ++)
    {
        QTreeWidgetItem* topItem = ui->treeWidget->topLevelItem(i);
        QString numData = topItem->data(0, kNumRole).toString();
        if (numData == num.c_str())
        {
            item = topItem;
            break;
        }
    }
    return item;
}

void MainWindow::updateWindowTitle()
{
    QString  title = AppSettings::getString("App/Title", "");
    setWindowTitle(title);
}

void MainWindow::on_clickClearFreq()
{
    m_freqList.clear();

    refreshProgramTree();
}

void MainWindow::on_clickClearProgram()
{
    m_programList.clear();

    refreshProgramTree();
}

void MainWindow::on_clickClearLoop()
{
    m_loopList.clear();
}

void MainWindow::loopPlay()
{
    stopAll();

    if (m_loopList.empty())
    {
        return;
    }

    int count = AppSettings::getInt("Loop/Layout", AppConst::LOOP_LAYOUT);
    if (count > (int)m_loopList.size())
    {
        count = (int)m_loopList.size();
    }

    for (int i = 0; i < count; ++ i)
    {
        int index = (m_loopIndex ++) % m_loopList.size();
        const tv::Program& program = m_loopList[index];
        start(i, program.url.c_str());
    }
}

void MainWindow::on_actionstop_triggered()
{
    stop(m_currentIndex);
}

void MainWindow::on_actionstopAll_triggered()
{
    stopAll();
}

void MainWindow::on_actionhideTool_triggered()
{
    bool visible = ui->mainToolBar->isVisible();
    visible = !visible;
    ui->mainToolBar->setVisible(visible);

    AppSettings::setBool("App/Toolbar", visible);
}

QString MainWindow::getUser()
{
    return getApp().getUser();
}
